home *** CD-ROM | disk | FTP | other *** search
/ .net (French) 1996 December / .net Magazine (FR) - Issue 02 - Dec 1996.iso / Utilpers / SUPERQUE / DATA.2 / FILTERS / PSINIT / GS_FONTS.PS < prev    next >
Text File  |  1995-11-15  |  20KB  |  651 lines

  1. %    Copyright (C) 1990, 1995 Aladdin Enterprises.  All rights reserved.
  2. %    Licensed to Zenographics Inc. (Irvine, California) by Artifex Software Inc.
  3. %    under the OEM Agreement of December 21st, 1993.
  4.  
  5. % Font initialization and management code.
  6.  
  7. % Define the default font.
  8. /defaultfontname /Courier def
  9.  
  10. % Define the name of the font map file.
  11. /fontmapname (Fontmap) def
  12.  
  13. % If DISKFONTS is true, we load individual CharStrings as they are needed.
  14. % (This is intended primarily for machines with very small memories.)
  15. % In this case, we define another dictionary, parallel to FontDirectory,
  16. % that retains an open file for every font loaded.
  17. /FontFileDirectory 10 dict def
  18.  
  19. % Load the font name -> font file name map.
  20. userdict /Fontmap FontDirectory maxlength dict put
  21. /.loadFontmap        % <file> .loadFontmap -
  22.  {  { dup token not { closefile exit } if
  23.         % stack: <file> fontname
  24.       1 index token not
  25.        { (File or alias name missing in Fontmap!  Giving up.\n) print flush
  26.          {.loadFontmap} 0 get 1 .quit
  27.        } if
  28.       dup type dup /stringtype eq exch /nametype eq or not
  29.        { (Invalid file or alias name in Fontmap!  Giving up.\n) print flush
  30.          {.loadFontmap} 0 get 1 .quit
  31.        } if
  32.         % stack: <file> fontname filename|aliasname
  33.         % Read and pop tokens until a semicolon.
  34.        { 2 index token not
  35.       { (Semicolon missing in Fontmap!  Giving up.\n) print flush
  36.         {.loadFontmap} 0 get 1 .quit
  37.       } if
  38.      dup /; eq { pop .definefontmap exit } if
  39.      pop
  40.        } loop
  41.     } loop 
  42.  } bind def
  43. % Make an entry in Fontmap.  We redefine this if the Level 2
  44. % resource machinery is loaded.
  45. /.definefontmap            % <fontname> <file|alias> .definefontmap -
  46.  { Fontmap 3 1 roll .growput
  47.  } bind def
  48.  
  49. % If there is no FONTPATH, get one from the environment.
  50. /FONTPATH where
  51.  { pop }
  52.  { (GS_FONTPATH) getenv { /FONTPATH exch def } if }
  53. ifelse
  54.  
  55. % If we can't find a Fontmap, try using the FONTPATH.
  56. fontmapname findlibfile
  57.  { exch pop .loadFontmap }
  58.  { pop /FONTPATH where
  59.     { pop }
  60.     { fontmapname /undefinedfilename signalerror }
  61.    ifelse
  62.  }
  63. ifelse
  64.  
  65. % Parse a font file just enough to find the FontName or FontType.
  66. /.findfontvalue        % <file> <key> .findfontvalue <name> true
  67.             % <file> <key> .findfontvalue false
  68.             % Closes the file in either case.
  69.  { exch dup read not { -1 } if
  70.    2 copy unread 16#80 eq
  71.     { dup (xxxxxx) readstring pop pop }        % skip .PFB header
  72.    if
  73.     { dup token not { false exit } if        % end of file
  74.       dup /eexec eq { pop false exit } if    % reached eexec section
  75.       dup /Subrs eq { pop false exit } if    % Subrs without eexec
  76.       dup /CharStrings eq { pop false exit } if    % CharStrings without eexec
  77.       dup 3 index eq
  78.        { xcheck not { dup token exit } if }    % found key
  79.        { pop }
  80.       ifelse
  81.     } loop
  82.    dup { 4 } { 3 } ifelse -2 roll closefile pop
  83.  } bind def
  84. /.findfontname
  85.  { /FontName .findfontvalue
  86.  } bind def
  87.  
  88. /FONTPATH where not { (%END FONTPATH) .skipeof } if
  89. pop
  90.  
  91. % Scan directories looking for plausible fonts.  "Plausible" means that
  92. % the file begins with %!PS-AdobeFont- or %!FontType1-, or with \200\001
  93. % followed by four arbitrary bytes and then either of these strings.
  94. % To speed up the search, we skip any file whose name appears in
  95. % the Fontmap (with any extension and upper/lower case variation) already,
  96. % and any file whose extension definitely indicates it is not a font.
  97. %
  98. % NOTE: The current implementation of this procedure is Unix/DOS-
  99. % specific.  It assumes that '/' and '\' are directory separators; that
  100. % the part of a file name following the last '.' is the extension;
  101. % that ';' cannot appear in a file name; and that ':' can appear in a
  102. % file name only if the file name doesn't begin with '/', '\', or '.'.
  103. % (this is so that Unix systems can use ':' as the separator).
  104. %
  105. /.lowerstring        % <string> .lowerstring <lowerstring>
  106.  { 0 1 2 index length 1 sub
  107.     { 2 copy get dup 65 ge exch 90 le and
  108.        { 2 copy 2 copy get 32 add put }
  109.      if pop
  110.     }
  111.    for
  112.  } bind def
  113. /.splitfilename        % <dir.../base.extn> .basename <base> <extn>
  114.  {  { (/) search { true } { (\\) search } ifelse
  115.        { pop pop }
  116.        { exit }
  117.       ifelse
  118.     }
  119.    loop
  120.    dup { (.) search { pop pop } { exit } ifelse } loop
  121.    2 copy eq
  122.     { pop () }
  123.     { exch dup length 2 index length 1 add sub 0 exch getinterval exch }
  124.    ifelse
  125. % Following is debugging code.
  126. %   (*** Split => ) print 2 copy exch ==only ( ) print ==only
  127. %   ( ***\n) print flush
  128.  } bind def
  129. /.scanfontdict Fontmap maxlength dict def
  130. /.scanfontbegin
  131.  {    % Construct the table of all file names already in Fontmap.
  132.    Fontmap
  133.     { exch pop dup type /stringtype eq
  134.        { .splitfilename pop =string copy .lowerstring cvn
  135.          .scanfontdict exch true .growput
  136.        }
  137.        { pop
  138.        }
  139.       ifelse
  140.     }
  141.    forall
  142.  } bind def
  143. /.scanfontskip mark
  144.         % Strings are converted to names anyway, so....
  145.   /afm true
  146.   /bat true
  147.   /c true
  148.   /cmd true
  149.   /com true
  150.   /dll true
  151.   /doc true
  152.   /exe true
  153.   /h true
  154.   /o true
  155.   /obj true
  156.   /pfm true
  157.   /txt true
  158. .dicttomark def
  159. /.scan1fontstring 128 string def
  160. /.fontheaders [(%!PS-AdobeFont-*) (%!FontType1-*)] def
  161. 0 .fontheaders { length max } forall 6 add    % extra for PFB header
  162. /.scan1fontfirst exch string def
  163. /.scan1fontdir        % <dirname> .scan1fontdir -
  164.  { QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
  165.    (/*) concatstrings 0 0 0 4 -1 roll    % found scanned files
  166.     {        % stack: <fontcount> <scancount> <filecount> <filename>
  167.       exch 1 add exch                   % increment filecount
  168.       dup .splitfilename .lowerstring
  169.         % stack: <fontcount> <scancount> <filecount+1> <filename>
  170.         %    <BASE> <ext>
  171.       .scanfontskip exch known exch .scanfontdict exch known or
  172.        { pop
  173.         % stack: <fontcount> <scancount> <filecount+1>
  174.        }
  175.        { 3 -1 roll 1 add 3 1 roll
  176.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  177.          dup (r) { file } stopped
  178.       { pop pop null () 
  179.         % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  180.         %    null ()
  181.           }
  182.       { 
  183.         % On some platforms, the file operator will open directories,
  184.         % but an error will occur if we try to read from one.
  185.         % Handle this possibility here.
  186.         dup .scan1fontfirst { readstring } stopped
  187.          { pop pop () }
  188.          { pop }
  189.         ifelse 
  190.         % stack: <fontcount> <scancount+1> <filecount+1>
  191.         %    <filename> <file> <header>
  192.           }
  193.      ifelse
  194.         % Check for PFB file header.
  195.      dup (\200\001????*) .stringmatch
  196.       { dup length 6 sub 6 exch getinterval }
  197.      if
  198.         % Check for font file headers.
  199.      false .fontheaders { 2 index exch .stringmatch or } forall exch pop
  200.       {    % stack: <fontcount> <scancount+1> <filecount+1> <filename>
  201.         %    <file>
  202.             dup 0 setfileposition .findfontname
  203.          { dup Fontmap exch known
  204.         { pop pop
  205.         }
  206.         { exch copystring exch
  207.           DEBUG { ( ) print dup =only } if
  208.           1 index .definefontmap
  209.           .splitfilename pop true .scanfontdict 3 1 roll .growput
  210.             % Increment fontcount.
  211.           3 -1 roll 1 add 3 1 roll
  212.         }
  213.            ifelse
  214.          }
  215.         if
  216.       }
  217.         % .findfontname will have done a closefile in the above case.
  218.       { dup null eq { pop } { closefile } ifelse pop 
  219.           }
  220.      ifelse
  221.        }
  222.       ifelse
  223.     }
  224.    .scan1fontstring filenameforall
  225.    QUIET
  226.     { pop pop pop }
  227.     { ( ) print =only ( files, ) print =only ( scanned, ) print
  228.       =only ( new fonts.\n) print flush
  229.     }
  230.    ifelse
  231.  } bind def
  232. % Scan all the directories mentioned in FONTPATH (or GS_FONTPATH).
  233. /FONTPATH where
  234.  { pop .scanfontbegin
  235.     % Parsing the list of dictionaries is messy, since we have to
  236.     % handle both the Unix : and the other-system ; as separators.
  237.     % See the earlier comment for the restrictions that make this work.
  238.    FONTPATH
  239.     { dup length 0 eq { pop exit } if
  240.       (;) search
  241.        { exch pop
  242.        }
  243.        { dup 0 1 getinterval (/\\.) exch search
  244.           { pop pop pop (:) search
  245.          { exch pop }
  246.          { () exch }
  247.         ifelse
  248.       }
  249.       { pop () exch
  250.       }
  251.      ifelse
  252.        }
  253.       ifelse .scan1fontdir
  254.     }
  255.    loop
  256.  }
  257. if
  258.  
  259. %END FONTPATH
  260.  
  261. % Define definefont.  This is a procedure built on a set of operators
  262. % that do all the error checking and key insertion.
  263. mark
  264.     /.buildfont0 where { pop 0 /.buildfont0 cvx } if
  265.     /.buildfont1 where { pop 1 /.buildfont1 cvx } if
  266.     /.buildfont3 where { pop 3 /.buildfont3 cvx } if
  267. .dicttomark /.buildfontdict exch def
  268. /.growfontdict
  269.  {    % Grow the font dictionary, if necessary, to ensure room for an
  270.     % added entry, making sure there is at least one slot left for FID.
  271.    dup maxlength 1 index length sub 2 lt
  272.     { dup dup wcheck
  273.        { .growdict }
  274.        { .growdictlength dict copy }
  275.       ifelse
  276.     }
  277.     { dup wcheck not { dup maxlength dict copy } if
  278.     }
  279.    ifelse
  280.  } bind def  
  281. /definefont
  282.  { 1 dict begin count /d exch def    % save stack depth in case of error
  283.     {        % Check for disabled platform fonts.
  284.       NOPLATFONTS
  285.        {    % Make sure we leave room for FID.
  286.      .growfontdict dup /ExactSize 0 put
  287.        }
  288.        {    % Hack: if the Encoding looks like it might be the
  289.         % Symbol or Dingbats encoding, load those now (for the
  290.         % benefit of platform font matching) just in case
  291.         % the font didn't actually reference them.
  292.      dup /Encoding get length 65 ge
  293.       { dup /Encoding get 64 get
  294.         dup /congruent eq { SymbolEncoding pop } if
  295.         /a9 eq { DingbatsEncoding pop } if
  296.       }
  297.      if
  298.        }
  299.       ifelse
  300.       dup /FontType get //.buildfontdict exch get exec
  301.       DISKFONTS
  302.        { FontFileDirectory 2 index known
  303.           { dup /FontFile FontFileDirectory 4 index get .growput
  304.       }
  305.      if
  306.        }
  307.       if
  308.       readonly
  309.     }
  310.    stopped
  311.     { count d sub { pop } repeat end /invalidfont signalerror
  312.     }
  313.     { end        % stack: name fontdict
  314.         % If the current allocation mode is global, also enter
  315.         % the font in LocalFontDirectory.
  316.       .currentglobal
  317.        { systemdict /LocalFontDirectory .knownget
  318.       { 2 index 2 index .growput }
  319.      if
  320.        }
  321.       if
  322.       dup FontDirectory 4 -2 roll .growput
  323.     }
  324.    ifelse
  325.  } odef
  326.  
  327. % Define a procedure for defining aliased fonts.
  328. % We can't just copy the font (or even use the same font unchanged),
  329. % because a significant number of PostScript files assume that
  330. % the FontName of a font is the same as the font resource name or
  331. % the key in [Shared]FontDirectory; on the other hand, some Adobe files
  332. % rely on the FontName of a substituted font *not* being the same as
  333. % the requested resource name.  We address this issue heuristically:
  334. % we substitute the new name iff the font name doesn't have MM in it.
  335. /.aliasfont        % <name> <font> .aliasfont <newFont>
  336.  { .currentglobal 3 1 roll dup .gcheck .setglobal
  337.    dup length 2 add dict
  338.    dup 3 -1 roll { 1 index /FID eq { pop pop } { put dup } ifelse } forall
  339.         % Stack: global fontname newfont newfont.
  340.         % We might be defining a global font whose FontName
  341.         % is a local string.  This is weird, but legal,
  342.         % and doesn't cause problems anywhere else.
  343.         % To avoid any possible problems, do a cvn.
  344.    2 index =string cvs (MM) search
  345.     { pop pop pop pop
  346.     }
  347.     { /FontName exch dup type /stringtype eq { cvn } if put
  348.     }
  349.    ifelse
  350.    systemdict /definefont get exec    % Don't bind, since Level 2
  351.                     % redefines definefont
  352.    exch .setglobal
  353.  } odef        % so findfont will bind it
  354.  
  355. % Define .loadfont for loading a font.  If we recognize Type 1 fonts,
  356. % gs_type1.ps will redefine this.
  357. /.loadfont { cvx exec } bind def
  358.  
  359. % Find an alternate font to substitute for an unknown one.
  360. % We go to some trouble to parse the font name and extract
  361. % properties from it.
  362. /.substitutefaces [
  363.     % Condensed or narrow fonts map to the only narrow family we have.
  364.   [(Condensed) /Helvetica-Narrow]
  365.   [(Narrow) /Helvetica-Narrow]
  366.     % If the family name appears in the font name,
  367.     % use a font from that family.
  368.   [(Avant) /AvantGarde]
  369.   [(Bookman) /Bookman]
  370.   [(Cour) /Courier]
  371.   [(Helv) /Helvetica]
  372.   [(Pala) /Palatino]
  373.   [(Schlbk) /NewCenturySchlbk]
  374.   [(Times) /Times]
  375.     % Guess at suitable substitutions for other fonts.
  376.   [(Grot) /Times]
  377.   [(Roman) /Times]
  378.   [(Book) /NewCenturySchlbk]
  379. ] readonly def
  380. /.substituteproperties [
  381.   [(Italic) 1] [(Oblique) 1]
  382.   [(Bold) 2] [(bold) 2] [(Demi) 2]
  383. ] readonly def
  384. /.substitutefamilies mark
  385.   /AvantGarde
  386.     {/AvantGarde-Book /AvantGarde-BookOblique
  387.      /AvantGarde-Demi /AvantGarde-DemiOblique}
  388.   /Bookman
  389.     {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic}
  390.   /Courier
  391.     {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique}
  392.   /Helvetica
  393.     {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique}
  394.   /Helvetica-Narrow
  395.     {/Helvetica-Narrow /Helvetica-Narrow-Oblique
  396.      /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique}
  397.   /NewCenturySchlbk
  398.     {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic
  399.      /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic}
  400.   /Palatino
  401.     {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic}
  402.   /Times
  403.     {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic}
  404. .dicttomark readonly def
  405. /.substitutefont        % <fontname> .substitutefont <altname>
  406.  {    % Look for properties and/or a face name in the font name.
  407.     % If we find any, use Helvetica as the base font;
  408.     % otherwise, use the default font.
  409.     % Note that the "substituted" font name may be the same as
  410.     % the requested one; the caller must check this.
  411.    dup length string cvs
  412.     {defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique}
  413.    exch 0 exch    % stack: fontname facelist properties fontname
  414.     % Look for a face name.
  415.    .substitutefaces
  416.     { 2 copy 0 get search
  417.        { pop pop pop 1 get .substitutefamilies exch get
  418.      4 -1 roll pop 3 1 roll
  419.        }
  420.        { pop pop
  421.        }
  422.       ifelse
  423.     }
  424.    forall
  425.    .substituteproperties
  426.     { 2 copy 0 get search
  427.        { pop pop pop 1 get 3 -1 roll or exch }
  428.        { pop pop }
  429.       ifelse
  430.     }
  431.    forall pop get exec
  432.     % Only accept fonts known in the Fontmap.
  433.    Fontmap 1 index known not { pop defaultfontname } if
  434.  } bind def
  435. % Substitute for a font, or indicate an error.
  436. /.findsubstfont        % -mark- <alias>* <fontname> .findsubstfont
  437.             %   -mark- <alias>* <fontname> <substname>
  438.  {        % If we're already trying to substitute for this name, give up.
  439.    counttomark 1 sub -1 1
  440.     { index 1 index eq
  441.        { QUIET not
  442.       { (Unable to substitute for font ) print dup cvx =only
  443.         (.\n) print flush
  444.       } if
  445.      /findfont cvx /invalidfont signalerror
  446.        }
  447.       if
  448.     }
  449.    for
  450.    dup .substitutefont
  451.    QUIET not
  452.     { (Substituting font ) print dup cvx =only
  453.       ( for ) print 1 index cvx = flush
  454.     } if
  455.  } bind def
  456.  
  457. % If requested, make (and recognize) fake entries in FontDirectory for fonts
  458. % present in Fontmap but not actually loaded.  Thanks to Ray Johnston for
  459. % the idea behind this code.
  460. FAKEFONTS not { (%END FAKEFONTS) .skipeof } if
  461.  
  462. % We use the presence or absence of the FontMatrix key to indicate whether
  463. % a font is real or fake.
  464.  
  465. /definefont        % <name> <font> definefont <font>
  466.  { dup /FontMatrix known not { /FontName get findfont } if
  467.    //definefont
  468.  } bind odef
  469.  
  470. /scalefont        % <font> <scale> scalefont <font>
  471.  { exch dup /FontMatrix known not { /FontName get findfont } if
  472.    exch //scalefont
  473.  } bind odef
  474.  
  475. /makefont        % <font> <matrix> makefont <font>
  476.  { exch dup /FontMatrix known not { /FontName get findfont } if
  477.    exch //makefont
  478.  } bind def
  479.  
  480. /setfont        % <font> setfont -
  481.  { dup /FontMatrix known not { /FontName get findfont } if
  482.    //setfont
  483.  } bind odef
  484.  
  485. % Now load all the fonts defined in the Fontmap into FontDirectory
  486. % as "fake" fonts i.e., font dicts with only FontName defined.
  487. Fontmap
  488.  { pop
  489.    FontDirectory 1 index known not
  490.     { 1 dict dup /FontName 3 index put        
  491.       FontDirectory 3 1 roll put
  492.     }
  493.    if
  494.  } forall
  495.  
  496. %END FAKEFONTS
  497.  
  498. % Define findfont so it tries to load a font if it's not found.
  499. % The Red Book requires that findfont be a procedure, not an operator.
  500. /findfont
  501.  {    % Since PostScript has no concept of goto, or even blocks with
  502.     % exits, we use a loop as a way to get an exitable scope.
  503.     % The loop is never executed more than once.
  504.    mark exch
  505.     { .findfontloop
  506.     } stopped
  507.     { counttomark 1 sub { pop } repeat exch pop stop
  508.     }
  509.     {    % Define any needed aliases.
  510.       counttomark 1 sub { .aliasfont } repeat
  511.       exch pop
  512.     }
  513.    ifelse
  514.  } bind def
  515. /.findfontloop
  516.  {  {        % Stack: mark <alias>* fontname
  517.  
  518.     dup FontDirectory exch .knownget    % Already loaded?
  519.      { FAKEFONTS { dup /FontMatrix known } { true } ifelse
  520.         { exch pop exit
  521.         }
  522.         {                % In FontDirectory, but fake.
  523.           pop FontDirectory 1 index undef
  524.         }
  525.        ifelse
  526.      }
  527.     if
  528.  
  529.     dup Fontmap exch .knownget not        % Unknown font name.
  530.      { dup defaultfontname eq
  531.         { (Default font ) print dup cvx =only
  532.           ( not found in Fontmap!  Giving up.\n) print flush
  533.           /findfont cvx /invalidfont signalerror
  534.         } if
  535.        .findsubstfont .findfontloop exit
  536.      }
  537.     if
  538.  
  539.     % Check for a font alias.
  540.     dup type /nametype eq
  541.      { .findfontloop exit
  542.      }
  543.     if
  544.  
  545.     % Check for a font with a procedural definition.
  546.     dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and
  547.      {    % The procedure will load the font.
  548.        exec .findfontloop exit
  549.      }
  550.     if
  551.  
  552.     % If we can't open the file, substitute for the font.
  553.     findlibfile
  554.      {    % Stack: fontname fontfilename fontfile
  555.        DISKFONTS
  556.         { .currentglobal true .setglobal
  557.           2 index (r) file
  558.           FontFileDirectory exch 4 index exch .growput
  559.           .setglobal
  560.         }
  561.        if
  562.        QUIET not
  563.         { (Loading ) print 2 index =only
  564.           ( font from ) print 1 index print (... ) print flush
  565.         }
  566.        if
  567.        % Load the font into local or global VM according to FontType.
  568.        /setglobal where
  569.         { pop /FontType .findfontvalue { 1 eq } { false } ifelse
  570.           currentglobal exch setglobal
  571.           1 index (r) file .loadfont FontDirectory exch
  572.           setglobal
  573.         }
  574.         { .loadfont FontDirectory
  575.         }
  576.        ifelse
  577.  
  578.         % Stack: fontname fontfilename fontdirectory
  579.        QUIET not
  580.         { systemdict /level2dict known
  581.            { .currentglobal false .setglobal vmstatus
  582.              true .setglobal vmstatus 3 -1 roll pop
  583.          6 -1 roll .setglobal 5
  584.            }
  585.            { vmstatus 3
  586.            }
  587.           ifelse { =only ( ) print } repeat
  588.           (done.\n) print flush
  589.         } if
  590.  
  591.        % Check to make sure the font was actually loaded.
  592.        dup 3 index known { pop pop .findfontloop exit } if
  593.  
  594.        % Maybe the file had a different FontName.
  595.        % See if we can get a FontName from the file, and if so,
  596.        % whether a font by that name exists now.
  597.        exch (r) file .findfontname
  598.         { 2 copy .knownget
  599.            {    % Yes.  Stack: origfontname fontdirectory filefontname fontdict
  600.          3 -1 roll pop exch
  601.          QUIET
  602.           { pop
  603.           }
  604.           { (Using ) print cvx =only
  605.             ( font for ) print 1 index cvx =only
  606.             (.\n) print flush
  607.           }
  608.          ifelse exit
  609.            }
  610.           if pop
  611.         }
  612.        if pop
  613.  
  614.        % The font definitely did not load correctly.
  615.        QUIET not
  616.         { (Loading ) print dup cvx =only
  617.           ( font failed.\n) print flush
  618.         } if
  619.        .findsubstfont .findfontloop exit
  620.      }
  621.     if
  622.  
  623.     % findlibfile failed, substitute the default font.
  624.     % Stack: fontname fontfilename
  625.     (Can't find \(or can't open\) font file )
  626.     2 index defaultfontname eq
  627.      { print print ( for default font \() print cvx =only
  628.        (\)!  Giving up.\n) print flush
  629.        /findfont cvx /invalidfont signalerror
  630.      }
  631.      { QUIET
  632.         { pop pop
  633.         }
  634.         { print print (.\n) print flush
  635.         }
  636.        ifelse
  637.        .findsubstfont .findfontloop
  638.      }
  639.     ifelse
  640.     exit
  641.  
  642.     } loop        % end of loop
  643.  
  644.  } bind def
  645.  
  646. % Define a procedure to load all known fonts.
  647. % This isn't likely to be very useful.
  648. /loadallfonts
  649.  { Fontmap { pop findfont pop } forall
  650.  } bind def
  651.